﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using DotNet.Common.Kit;

namespace taobaoSpider
{
    /// <summary>
    /// http://shopsearch.taobao.com/search?
    /// q=9999&  关键词
    /// ratesum=11%2C15&         店铺等级(皇冠，钻石，心级)
    /// loc=%C9%CF%BA%A3&isb=0&  所在地
    /// rele_field=wangwang&     旺旺名称  ，店铺名称
    /// goodrate=9900%2C&        好评率
    /// fs=1
    /// s=80  页码，表示为第五页(每页20个，以0为索引开始，最多100页)
    /// </summary>
    public class HtmlShopSearch
    {
        private ShowErrorLogEventHandler ShowErrHandler = null;
        LogerHelper logger = new LogerHelper(DirType.Local, MessageType.Exception);
        static int ipIndex = 0, ipCount = 1; string currentIP = "本机IP";//代理服务器时用来计算取的索引和代理IP总数目 currentIP当前采集用的IP

        IniHelper ini = new IniHelper("HtmlNodeXPath.ini");
        System.Windows.Forms.Label lblInfo = new System.Windows.Forms.Label();
        System.Windows.Forms.Label lblIpInfo = new System.Windows.Forms.Label();
        HttpHelper httpHelper = new HttpHelper();
        HttpItem item = new HttpItem();
         //   lblInfo.Name = "lblInfo";
//lblIpInfo.Name = "lblIpInfo";

        string _nickName = "";  //输入参数
        string _nickNameVal = ""; //输入参数
        string _shopUrl = "";   //输出参数
        string _shopUrlXpath = "";  //输入参数
        string _nickNameXpath = ""; //input
        public string ShopUrl
        {
            get { return _shopUrl; }
        }
        public string NickName
        {
            set { _nickName = value; }
        }
        public string NickNameVal
        {
            set { _nickNameVal = value; }
        }
        public string ShopUrlXpath
        {
            set { _shopUrlXpath = value; }
        }
        public string NickNameXpath
        {
            set { _nickNameXpath = value; }
        }

        public void ShowCloseSystemForm(object sender)
        {
            frmCloseSystem frm = new frmCloseSystem();
            DialogResult drRet = frm.ShowDialog();
        }

        public HtmlShopSearch(ShowErrorLogEventHandler showErr, string shopUrlXpath, string nickXpath)
        {
            this.ShowErrHandler = showErr;
            this._shopUrlXpath = shopUrlXpath;
            this._nickNameXpath = nickXpath;

            lblInfo.Name = "lblInfo";
            lblIpInfo.Name = "lblIpInfo";
        }

        /// <summary>
        /// 解析While循环中的htmlStr得到相应的值。
        /// </summary>
        /// <param name="htmlStr"></param>
        /// <returns></returns>
        private string ParseHtmlStrWhile(string htmlStr)
        {
            if (htmlStr.Contains("title"))  //说明返回为一个HTML页面
            {
                HtmlAgilityPack.HtmlDocument doc = GlobalFun.ParaseToHtml(htmlStr);
                htmlStr = doc.DocumentNode.SelectNodes("//title")[0].InnerText.Trim('\r', '\n');
                return htmlStr;
            }
            else
            {
                if (htmlStr.Contains("body"))
                {
                    HtmlAgilityPack.HtmlDocument doc = GlobalFun.ParaseToHtml(htmlStr);
                    htmlStr = doc.DocumentNode.SelectNodes("//body")[0].InnerText.Trim('\r', '\n');
                    return htmlStr;
                }
                else
                {
                    return htmlStr;
                }
            }
        }
        //http://s.taobao.com/search?q=lhl62411570&app=shopsearch
        public string InitOneShopUrl()
        {
            ShowErrorLogEventArgs e =new ShowErrorLogEventArgs();
            string url = "http://s.taobao.com/search?q=" + System.Web.HttpUtility.UrlEncode(this._nickName) + "&rele_field=wangwang&fs=1&s=0&app=shopsearch";
            item.URL = url;
            item.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50215;)";
            string htmlStr = httpHelper.GetHtml(item).Html;//循环变量初值
            HtmlAgilityPack.HtmlDocument doc = GlobalFun.ParaseToHtml(htmlStr);
            HtmlAgilityPack.HtmlNodeCollection shopUrlHnc = doc.DocumentNode.SelectNodes(_shopUrlXpath);//循环变量初值

            DateTime closeInitTime = DateTime.Now; //标识关机时间起点。
            while (!htmlStr.Contains("淘宝搜索")||shopUrlHnc==null)//应该有一个退出机制，避免出现死循环
            {  //当shopUrlHnc=null说明附加的条件太多，如果还为null
                DateTime closeEndTime = DateTime.Now;
                string htmlStrTitle = ParseHtmlStrWhile(htmlStr); //用来标识进入路由重启或换IP的标识串。
                e.ErrPosition = "ShopSearch:InitOneShopUrl()=>while";
                //////start  更新数据要联动
                logger.LogToFile(e.ErrPosition + htmlStrTitle+ "--掌柜名：" + this._nickName);
                e.ErrMessage = htmlStrTitle + "  nickname:" + this._nickName;
                this.ShowErrHandler(lblInfo, e);
                //e.ErrMessage = "本次使用IP：" + currentIP;
                //this.ShowErrHandler(lblIpInfo, e);
                ///////////end

                if (closeEndTime > closeInitTime.AddMinutes(5)) //超时10分钟则进入关机程序或者换代理IP
                {
                    if (ini.GetKeyValue("ProxyUseFlag", "closeSys") == "0")  //进入关机程序
                    {
                        e.ErrMessage = "开始循环时间：" + closeInitTime + "  结束循环关机时间" + closeEndTime;

                        logger.LogToFile(e.ErrPosition + "--超时5分钟关机--" + htmlStrTitle);
                        e.ErrMessage = "--超时5分钟关机--"+htmlStrTitle;
                        ShowErrHandler(lblInfo, e);
                        e.ErrMessage = "可用代理IP数：-1" + "\r\n" + "IP索引：-1" + "\r\n" + "本次使用IP：" + currentIP;
                        this.ShowErrHandler(lblIpInfo, e);
                       
                        this.ShowErrHandler("closeSys", e);//调用关机程序
                    }
                    if (ini.GetKeyValue("ProxyUseFlag", "closeSys") == "1")  //换是个机IP访问
                    {
                        if (currentIP == "本机IP" || currentIP == "")
                        {
                            item.ProxyIp = "";
                            TBWS.tb_wsSoapClient client = new TBWS.tb_wsSoapClient();
                            currentIP = client.GetReqIp() + "(本机IP)";
                        }
                        htmlStr = httpHelper.GetHtml(item).Html;
                        htmlStrTitle = ParseHtmlStrWhile(htmlStr); //用来标识进入路由重启或换IP的标识串。
                       //以下三者信息进行联动，便于监测程序运行状况
                        logger.LogToFile(e.ErrPosition + "--超时5分钟换本机IP--" + htmlStrTitle);
                        e.ErrMessage = "--超时5分钟换本机IP--" + htmlStrTitle;
                        this.ShowErrHandler(lblInfo, e);
                        e.ErrMessage = "可用代理IP数：-1" + "\r\n" + "IP索引：-1" + "\r\n" + "本次使用IP：" + currentIP;
                        this.ShowErrHandler(lblIpInfo, e);
                    }
                }

                Dictionary<string, string> dict = ini.SectionValuesEx("ReConnectRouter"); //读取INI中设定的重启路由的条件
                if (GlobalFun.ExistDict(dict, htmlStrTitle))
                {
                    if (ini.GetKeyValue("ProxyUseFlag", "proxy") == "0")
                    {
                        currentIP = Router.DisConnect();
                        logger.LogToFile(e.ErrPosition + "重启路由IP:" + currentIP);
                        e.ErrMessage = htmlStrTitle + "  " + this._nickName;
                        ShowErrHandler(lblInfo, e);
                        e.ErrMessage = "重启路由IP--" + ipCount + "\r\n" + "IP索引--" + ipIndex + "\r\n" + "本次使用IP--" + currentIP;
                        this.ShowErrHandler(lblIpInfo, e);
                    }
                    if (ini.GetKeyValue("ProxyUseFlag", "proxy") == "1")
                    {
                        ipCount = 0;
                        //if (ipCount != 0)
                        //    ipIndex = ipIndex % ipCount;
                        Router.ShowErrHandler = this.ShowErrHandler;
                        string vtime = "";
                        currentIP = Router.ProxyIp(ref ipIndex, ref ipCount,ref vtime);
                        if (currentIP == "本机IP" || currentIP == "")
                        {
                            item.ProxyIp = "";
                            TBWS.tb_wsSoapClient client = new TBWS.tb_wsSoapClient();
                            currentIP = client.GetReqIp() + "(本机IP)";
                        }
                        logger.LogToFile(e.ErrPosition + "代理IP数--" + ipCount + "--第" + ipIndex + "--号IP：" + currentIP);
                        e.ErrMessage = htmlStrTitle+"  "+this._nickName;
                        ShowErrHandler(lblInfo, e);
                        e.ErrMessage = "可用代理IP数：" + ipCount + "\r\n" + "IP索引：" + ipIndex + "\r\n" + "本次使用IP：" + currentIP+"(速度:"+vtime+" s)";
                        this.ShowErrHandler(lblIpInfo, e);
                        //ipIndex++;
                    }
                }
                item.URL = "http://s.taobao.com/search?q=" + System.Web.HttpUtility.UrlEncode(this._nickName) + "&app=shopsearch&s=0";
                DateTime d1 = DateTime.Now;
                htmlStr = httpHelper.GetHtml(item).Html;
                DateTime d2 = DateTime.Now;
                Router.RefreshTime(currentIP, (d2 - d1).Ticks / 10000);
                shopUrlHnc = GlobalFun.ParaseToHtml(htmlStr).DocumentNode.SelectNodes(_shopUrlXpath);
                if (shopUrlHnc == null && htmlStr.Contains("淘宝搜索"))  //再次进入后还为null则退出。但如果此时没有得到搜索页面不能退出。
                {
                    break;
                }
            }
            if (shopUrlHnc != null)
            {
                HtmlAgilityPack.HtmlNodeCollection nickNameHnc = GlobalFun.ParaseToHtml(htmlStr).DocumentNode.SelectNodes(_nickNameXpath);
                for (int i = 0; i < shopUrlHnc.Count; i++)
                {
                    if (nickNameHnc[i].InnerText.Trim() == _nickName)
                    {
                        this._shopUrl = shopUrlHnc[i].Attributes["href"].Value;
                        break;
                    }
                }

            }
            else
            {
                e.ErrPosition = "ShopSearch:InitOneShopUrl()";
                e.ErrMessage = "正在查找掌柜--" + this._nickName + "--"+this._nickNameVal+"的店铺首页不存在";
                this.ShowErrHandler(lblInfo, e);
                //GlobalFun.WriteErrorLog(e.ErrPosition, e.ErrMessage);
                logger.WriteErrorLog(e.ErrPosition + e.ErrMessage);
            }
            //此处正确的流程在ShopIndex:InitDianpuIndex()作为互补
            return this._shopUrl;
        }
    }
}


